/*
 * Copyright 2023, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 */

#include <asm_defs.h>

/* 
 * 实现原子操作的__haiku_compare_and_swap32汇编版本
 * 函数原型：int32 __haiku_compare_and_swap32(int32 *value, int32 oldValue, int32 newValue)
 * 参数：
 *   - a0: value的地址
 *   - a1: oldValue
 *   - a2: newValue
 * 返回值：
 *   - a0: 操作前value的值
 */
FUNCTION(__haiku_compare_and_swap32):
	// 保存返回地址
	addi.d	sp, sp, -16
	st.d	ra, sp, 0

	// 执行原子比较和交换操作
	// LoongArch64的ll.w和sc.w指令用于实现原子操作
	// ll.w加载链接的字，sc.w条件存储字
1:
	ll.w	t0, a0, 0      // 加载当前值到t0
	bne	t0, a1, 2f     // 如果当前值不等于oldValue，跳转到2
	sc.w	a2, a0, 0      // 尝试将newValue存储到地址
	beqz	a3, 1b        // 如果存储失败，重试

2:
	mov	a0, t0         // 返回操作前的值

	// 恢复返回地址并返回
	ld.d	ra, sp, 0
	addi.d	sp, sp, 16
	ret
FUNCTION_END(__haiku_compare_and_swap32)

/* 
 * 实现64位原子操作的__haiku_compare_and_swap64汇编版本
 * 函数原型：int64 __haiku_compare_and_swap64(int64 *value, int64 oldValue, int64 newValue)
 * 参数：
 *   - a0: value的地址
 *   - a1: oldValue
 *   - a2: newValue
 * 返回值：
 *   - a0: 操作前value的值
 */
FUNCTION(__haiku_compare_and_swap64):
	// 保存返回地址
	addi.d	sp, sp, -16
	st.d	ra, sp, 0

	// 执行原子比较和交换操作
	// LoongArch64的ll.d和sc.d指令用于实现64位原子操作
1:
	ll.d	t0, a0, 0      // 加载当前值到t0
	bne	t0, a1, 2f     // 如果当前值不等于oldValue，跳转到2
	sc.d	a2, a0, 0      // 尝试将newValue存储到地址
	beqz	a3, 1b        // 如果存储失败，重试

2:
	mov	a0, t0         // 返回操作前的值

	// 恢复返回地址并返回
	ld.d	ra, sp, 0
	addi.d	sp, sp, 16
	ret
FUNCTION_END(__haiku_compare_and_swap64)